#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <asm/desc_defs.h>
#include <linux/cred.h>
#include <linux/uidgid.h>
#include <linux/tty.h>
#include "cli.h"

unsigned long idt_addr = 0;
unsigned long old_handler = 0;
unsigned long new_handler = 0;

#pragma pack(1)
typedef struct {
        unsigned short offset_low,seg_selector;
        unsigned char reserved,flag;
        unsigned short offset_high;
        } idt_t;
idt_t *idt;

struct desc_ptr idtr;

unsigned long get_idt_addr(void){
	asm ("sidt %0":"=m" (idtr));
	return(idtr.address);
	}

void set_new_idt(void){
	unsigned long flags;
	idt = (idt_t*)kmalloc(256*sizeof(idt_t), GFP_KERNEL);

	memcpy(idt, (idt_t*)idt_addr, 256*sizeof(idt_t));
	idtr.address = (unsigned long)idt;
	
	save_flags(flags);
	cli();
	asm("lidt %0"::"m" (idtr));
	restore_flags(flags);
	}

void set_handler( int i, unsigned long new_addr){
	idt[i].offset_high = (unsigned short)(new_addr >> 16);
	idt[i].offset_low = (unsigned short)(new_addr & 0x0000ffff);
	}

unsigned long get_handler( int i){
	return ((idt[i].offset_high << 16) | idt[i].offset_low);
	}

void my_handler(void){
		printk(KERN_ALERT "EXCPTION #BP occurred!\n");
		}

void stub(void){
	asm volatile ( 	"       call  %0                  \n"
			"       jmp  %1                 \n"
        ::"m"(new_handler), "m"(old_handler));
	}
